﻿/***
    This file is part of Qasparov.

    Qasparov is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Qasparov is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Qasparov. If not, see <http://www.gnu.org/licenses/>.

 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Com.Oxilly.Qsb.Core.SDK.EF
{
    public abstract class QAppBase : IQApp
    {
        public enum QAppStates
        {
            RUNNING,
            PAUSED,
            HALTED
        }

        private QAppStates state;
        private QsbEngineApi api;

        //Implementing the IQApp interface explicit makes the methods invisible for the derived classes
        //This makes it harder (not impossible) for QApp programmers to mistakenly call the methods unintended.
        #region IQApp Implementation
        void IQApp.SetEngine(QsbEngineApi api)
        {
            this.api = api;
        }

        void IQApp.StartUp()
        {
            OnStart(api);
            OnActivate(api);
            state = QAppStates.RUNNING;
        }

        //Entery point for the QsbEvents
        void IQApp.ProcessQsbEvent(QsbEngineApi api, Events.QsbEventArgs e)
        {
            if (Filter(api, e))
            {
                if (state == QAppStates.HALTED)
                {
                    OnStart(api);
                    OnActivate(api);
                    state = QAppStates.RUNNING;
                }
                else if (state == QAppStates.PAUSED)
                {
                    OnResume(api);
                    OnActivate(api);
                    state = QAppStates.RUNNING;
                }
                OnQsbEvent(api, e);
            }
        }

        void IQApp.ProcessQsbMessage(QsbEngineApi api, API.QsbMessage msg)
        {
            // Let QApp's handel messages one by one.
            // Locking on this will prevent only the current QApp to handel the next message.
            // Other QApp's will still receive the same message.
            // Threads are not garantied to be released in the same order as they block (mostly they will not)
            // This means that messages will not be processes by every QApp in the same order, nor at te same time.
            lock (this)
            {
                try
                {
                    Log(String.Format("Processing Msg[{0}] '{1}' in QApp[{2}]",
                            msg.Number,
                            msg.Description,
                            this.Name));
                    OnQsbMessageReceived(api, msg);
                    Log(String.Format("Done processing Msg[{0}] '{1}' in QApp[{2}]",
                            msg.Number,
                            msg.Description,
                            this.Name));
                }
                catch (Exception ex)
                {
                    Log(String.Format("Exception in QApp [{0}]: {1}",
                            this.Name,
                            ex.Message),
                        System.Diagnostics.SourceLevels.Error);
                }
            }
        }

        void IQApp.ReleaseResources()
        {
            OnReleaseResources();
        }

        
        #endregion

        #region Abstract Methods
        /// <summary>
        /// Filters the event. When returing 'false', the extension does not become active
        /// </summary>
        /// <param name="api"></param>
        /// <param name="e"></param>
        /// <returns>True when the extention must process the event</returns>
        protected abstract bool Filter(Com.Oxilly.Qsb.Core.SDK.QsbEngineApi api, Com.Oxilly.Qsb.Core.SDK.Events.QsbEventArgs e); 

        protected abstract void OnQsbMessageReceived(QsbEngineApi api, API.QsbMessage message);

        protected abstract void OnQsbEvent(Com.Oxilly.Qsb.Core.SDK.QsbEngineApi api, Com.Oxilly.Qsb.Core.SDK.Events.QsbEventArgs e);

        protected abstract void OnReleaseResources();
        
        #endregion

        #region Default implementations
        protected virtual void OnActivate(Com.Oxilly.Qsb.Core.SDK.QsbEngineApi api)
        {

        }

        protected virtual void OnStart(Com.Oxilly.Qsb.Core.SDK.QsbEngineApi api)
        {

        }
        
  
        protected virtual void OnResume(Com.Oxilly.Qsb.Core.SDK.QsbEngineApi api)
        {

        }

        /// <summary>
        /// Returns the name of the Extension, by default this is the FullName of the class
        /// </summary>
        public string Name
        {
            get { return this.GetType().FullName; }
        }

        #endregion

        protected void Log(string msg, System.Diagnostics.SourceLevels level = System.Diagnostics.SourceLevels.Verbose)
        {
            //TODO:Implement Logging throug Log Manager (or with events)
            System.Diagnostics.EventLog.WriteEntry(this.Name, msg);
            //this.api.Log(new Events.LogEventArgs
            //{
            //    Level = level,
            //    Message = msg,
            //    Source = this.Name
            //}); 
        }
    }
}
